### adsb_parser/structures.py

from construct import *

# FPGA_TO_ADSB_FILE_ELEMENT 结构（24字节）
FPGA_TO_ADSB_FILE_ELEMENT = Struct(
    "timestamp" / BitStruct(
        "validityFlag" / Flag,
        "year" / BitsInteger(14),
        "month" / BitsInteger(4),
        "day" / BitsInteger(5),
        "hour" / BitsInteger(5),
        "minute_high" / BitsInteger(3),
        "minute_low" / BitsInteger(3),
        "second" / BitsInteger(6),
        "millisecond" / BitsInteger(10),
        "reserved" / BitsInteger(13)
    ),
    "msgInfo1" / Bytes(14),
    "signLevel" / Int8ul,
    "receiveAntennas" / BitStruct(
        "receive" / BitsInteger(1),
        "reserved" / BitsInteger(7)
    )
)

# ADSB_FAULT_WORD（4字节）
def parse_ADSB_Fault_Status(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        MA51_ACAS_ADSB_OUT_FAULT_EICAS      = raw >> 0 & 0x1,
        MA51_ACAS_ADSB_IN_SYSTEM_FAULT      = raw >> 1 & 0x1,
        MA51_ACAS_VSA_OWNSHIP_QUALIFIED     = raw >> 2 & 0x1,
        MA51_ACAS_ADSB_IN_ENABLED_OSS       = raw >> 3 & 0x1,
        ABNORMAL_INPUT_COMM_OF_TCAS         = raw >> 4 & 0x1,
        ABNORMAL_INPUT_COMM_OF_FPGA         = raw >> 5 & 0x1,
        ABNORMAL_INPUT_COMM_OF_IO           = raw >> 6 & 0x1,
        ICAO_Address_Fault                  = raw >> 7 & 0x1,
        TMP_Mode_Control_Fault              = raw >> 8 & 0x1,
        Ownship_Hori_Position_Fault         = raw >> 9 & 0x1,
        Ownship_Vert_Position_Fault         = raw >> 10& 0x1,
        Ownship_Not_Qualified_for_AIRB      = raw >> 11& 0x1,
        ADSB_OUT_Type_0_Trigged             = raw >> 12& 0x1,
        Top_RF_TX_Channel_Fault             = raw >> 13& 0x1,
        Bot_RF_TX_Channel_Fault             = raw >> 14& 0x1,
        Top_RF_RX_Channel_Fault             = raw >> 15& 0x1,
        Bot_RF_RX_Channel_Fault             = raw >> 16& 0x1,
        Top_Ant_Impedance_Fault             = raw >> 17& 0x1,
        Bot_Ant_Impedance_Fault             = raw >> 18& 0x1,
        Top_Self_TX_RX_Fault                = raw >> 19& 0x1,
        Bot_Self_TX_RX_Fault                = raw >> 20& 0x1,
        Broadcast_Monitoring_Fault          = raw >> 21& 0x1,
        PAD                                 = raw >> 22& 0x3FF,
    )

def parse_OWNSHIP_STATUS_INFO_bitfield1(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        Sensitivity_Level_Control = raw >>  0 & 0xFF,
        ADSB_OUT_mode =             raw >>  8 & 0xFF,
        ADSB_IN_mode =              raw >> 16 & 0xFF,
        Altitude_Select =           raw >> 24 & 0x7,
        Intruder_Altitude =         raw >> 27 & 0x7,
        pad1 =                      raw >> 30 & 0x3,
    )

def parse_OWNSHIP_STATUS_INFO_bitfield2(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        ND_TFC_ADSB_Selection_Fo =      raw >> 0 & 0x7,
        ND_TFC_ADSB_Selection_Capt =    raw >> 3 & 0x7,
        HSI_TFC_ADSB_Selection_Fo =     raw >> 6 & 0x7,
        HSI_TFC_ADSB_Selection_Capt =   raw >> 9 & 0x7,
        pad2 =                          raw >> 12 & 0xFFFFF,
    )

OWNSHIP_STATUS_INFO = Struct(
    # 前32位位域
"bitfield1_raw" / Bytes(4),
    "bitfield1" / Computed(lambda ctx: parse_OWNSHIP_STATUS_INFO_bitfield1(ctx.bitfield1_raw)),
    # 嵌套结构体（ADSB_FAULT_WORD）
    "ADSB_Fault_Status_raw" / Bytes(4),
    "ADSB_Fault_Status" / Computed(lambda ctx: parse_ADSB_Fault_Status(ctx.ADSB_Fault_Status_raw)),
    # 接下来的位域32位
    "bitfield2_raw" / Bytes(4),
    "bitfield2" / Computed(lambda ctx: parse_OWNSHIP_STATUS_INFO_bitfield2(ctx.bitfield2_raw)),
    # sw_number 字符数组
    "sw_number" / Bytes(16),
    # Pad_3 数组
    "Pad_3" / Int32ul
)

def parse_bitfield1(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        emergency_priority_status = raw >> 0 & 0x7FFF,
        air_gnd_status =            raw >> 15 & 0X1,
    )

def parse_bitfield2(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        validity_flag_traffic_dir =  raw >> 0 & 0x1,
        vertical_sense =             raw >> 1 & 0x3,
        tcas_tag =                   raw >> 3 & 0x1,
        traffic_qualified_for_vsa = raw >> 4 & 0x1,
        nacp =                       raw >> 5 & 0x3F,
        nacv =                       raw >> 11 & 0x3F,
        selection_mark =            raw >> 17 & 0x1,
        selection_vsa_mark =        raw >> 18 & 0x1,
        relative_alt_validity =     raw >> 19 & 0x1,
        bearing_validity =          raw >> 20 & 0x1,
        function_test_active =      raw >> 21 & 0x1,
        vertical_speed_type =       raw >> 22 & 0x1,
        geo_vertical_speed_validity = raw >> 23 & 0x1,
        baro_vertical_speed_validity = raw >> 24 & 0x1,
        intruder_sensitivity_level = raw >> 25 & 0x7F,
    )

def parse_bitfield3(raw_bytes):
    raw = int.from_bytes(raw_bytes, byteorder='little')
    return Container(
        ew_ns_velocity_validity =   raw >> 0 & 0x1,
        P_1 =                       raw >> 1 & 0x7FFFFFFF,
    )

# ASSAP_OUTPUT_FILE_ELEMENT
ASSAP_OUTPUT_FILE_ELEMENT = Struct(
    "bintime" / Float64l,
    "num" / Int32sl,
    "target_unique_id" / Int32sl,
    "type" / Int16ul,
    "tcas_alert_status" / Int16ul,
    "flight_id" / Bytes(8),
    "emitter_cat" / Int16ul,

    "bitfield1_raw" / Bytes(2), # 原始位域数据
    #以下通过位操作解析位域数据，定义一个派生字段，不会从二进制中读取任何数据，只是运行一个函数，基于已知字段计算结果，不占用额外的输入数据字节
    "bitfield1" / Computed(lambda ctx: parse_bitfield1(ctx.bitfield1_raw)),

    "x" / Int32sl,
    "y" / Int32sl,
    "z" / Int32sl,
    "lat" / Float64l,
    "lon" / Float64l,
    "alt" / Float64l,
    "range" / Int32sl,
    "bearing" / Float32l,
    "relative_alt" / Float32l,
    "ns_v" / Float32l,
    "ew_v" / Float32l,
    "track_hdg_trk" / Float32l,
    "ground_speed" / Int32sl,
    "dgs" / Int32sl,

    "bitfield2_raw" / Bytes(4),  # 原始位域数据
    #以下通过位操作解析位域数据，定义一个派生字段，不会从二进制中读取任何数据，只是运行一个函数，基于已知字段计算结果，不占用额外的输入数据字节
    "bitfield2" / Computed(lambda ctx: parse_bitfield2(ctx.bitfield2_raw)),

    "vertical_speed" / Float32l,

    "bitfield3_raw" / Bytes(4),  # 原始位域数据
    # 以下通过位操作解析位域数据，定义一个派生字段，不会从二进制中读取任何数据，只是运行一个函数，基于已知字段计算结果，不占用额外的输入数据字节
    "bitfield3" / Computed(lambda ctx: parse_bitfield3(ctx.bitfield3_raw))
)


# ASSAP_OUTPUT_FILE（11760字节）
ASSAP_OUTPUT_FILE = Struct(
    "FrameHeader" / Int32ul,
    "FrameNumber" / Int32ul,
    "ownship_qualified_for_airb" / Int32ul,
    "ownship_qualified_for_vsa" / Int32ul,
    "airb_status" / Int32ul,
    "vsa_status" / Int32ul,
    "targets_num" / Int32ul,
    "targets_num_only_tcas" / Int32ul,
    "targets_num_airborne" / Int32ul,
    "targets_num_surface" / Int32ul,
    "targets" / Array(61, ASSAP_OUTPUT_FILE_ELEMENT),
    "ownship_status_infomation" / OWNSHIP_STATUS_INFO,
    "ADSB_MSG_Validity_Num" / Int32ul,
    "targets_adsbMsg" / Array(200, FPGA_TO_ADSB_FILE_ELEMENT),
    "reserve" / Array(11, Int32ul),
    "crcCheck" / Int32ul,
    "FrameTail" / Int32ul
)
